home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 090 / cvar.arc / CVAR.C next >
Encoding:
C/C++ Source or Header  |  1986-05-05  |  19.0 KB  |  908 lines

  1. #include <stdio.h>
  2.  
  3. /*
  4.  * Data declaration keywords
  5.  */
  6. #define DEFINE      1
  7. #define INCLUDE      2
  8. #define TYPEDEF      3
  9. #define EXTERN      4
  10. #define STATIC      5
  11. #define AUTO      6
  12. #define REGISTER   7
  13. #define UNSIGNED   8
  14. #define CHAR      9
  15. #define INT      10
  16. #define LONG      11
  17. #define FLOAT      12
  18. #define DOUBLE      13
  19. #define STRUCT      14
  20. #define UNION      15
  21. #define VOID      16
  22. #define ENUM      17
  23.  
  24. #define DECLARATIONS   ENUM
  25. /*
  26.  * Other keywords
  27.  */
  28. #define IF      18
  29. #define ELSE      19
  30. #define FOR      20
  31. #define DO      21
  32. #define WHILE      22
  33. #define BREAK      23
  34. #define CONTINUE   24
  35. #define GOTO      25
  36. #define RETURN      26
  37. #define SWITCH      27
  38. #define CASE      28
  39. #define DEFAULT      29
  40. #define SIZEOF      30
  41.  
  42. #define KEYWORDS   SIZEOF
  43.  
  44. #define SYMBOL      31
  45. #define NEWLINE      127
  46.  
  47. /*
  48.  * File stuff:
  49.  */
  50. char *Filename;         /* current input file name */
  51. #ifdef BDS_C
  52. char Fileptr[BUFSIZ];      /* and I/O buffer for BDS C */
  53. #else
  54. FILE *Fileptr;         /* everybody else uses a file pointer */
  55. #endif
  56. int Inline;         /* current input line number */
  57. #define PAGELEN   55      /* max page length */
  58. int Outline;         /* current output line # for paginating */
  59. int Page;
  60.  
  61. #define FILESTACKSZ 10      /* maximum #include nesting */
  62. #define FILENMSZ 20      /* maximum file name length */
  63. struct fstack {         /* #include file stack */
  64.    char fname[FILENMSZ];   /* name of current file (before #include) */
  65. #ifdef BDS_C
  66.    char fptr[BUFSIZ];   /* and its file I/O buffer */
  67. #else
  68.    FILE *fptr;      /* or file ptr respectively */
  69. #endif
  70.    int fline;      /* line # in current file */
  71.    char fbraces;      /* current {} count */
  72.    char fparens;      /* current () count */
  73. } Filestack[ FILESTACKSZ ];
  74. int Nextfile;         /* next available slot in Filestack */
  75.  
  76. #define OUTBUFSZ 2000
  77. char Outbuf[ OUTBUFSZ ];   /* output buffer */
  78. char *Outend;         /* points to end of Outbuf */
  79. char *Nextout;         /* points to next position in Outbuf */
  80.  
  81. /*
  82.  * Command line flags
  83.  */
  84. char Doincludes;      /* process #include files */
  85. char Docomments;      /* print comments */
  86. char Dodefines;         /* print #define statements */
  87. char Debug;         /* program debug enable flag */
  88.  
  89. /*
  90.  * Parser variables
  91.  */
  92. #define TOKENBUFSZ   2000   /* largest string or comment block */
  93. char Tokenbuf[ TOKENBUFSZ+4 ];   /* current input "token" */
  94. char *Tokenstart;      /* ptr to first non-space char in Tokenbuf */
  95. char Token;         /* first non-space char in Tokenbuf */
  96. char Braces, Parens;      /* {} and () parity counters */
  97.  
  98. /*
  99.  * Current function information
  100.  */
  101. #define MAXLINELEN   80
  102. char Curfunc[ MAXLINELEN ];   /* name of current function */
  103. #define MAXREFS      500
  104. char *Refers[ MAXREFS ];   /* references to symbols made by Curfunc */
  105. int Nextref;
  106.  
  107.  
  108. main( argc, argv )
  109. int argc;
  110. char **argv;
  111. {
  112.    /*
  113.     * Initialize some pointers first.
  114.     */
  115.    Nextout = Outbuf;
  116.    Outend = Outbuf + OUTBUFSZ;
  117.  
  118.    /*
  119.     * Pares command line arguments.
  120.     */
  121.    while ( --argc )
  122.    {
  123.       if ( **++argv=='-' )
  124.       {
  125.          switch ( toupper( *++*argv ) )
  126.          {
  127.          case 'I':
  128.             Doincludes = 1;
  129.             break;
  130.          case 'C':
  131.             Docomments = 1;
  132.             break;
  133.          case 'D':
  134.             Dodefines = 1;
  135.             break;
  136.          case 'Y':
  137.             ++Debug;
  138.             break;
  139.          default:
  140.             usage();
  141.          }
  142.       }
  143.       else
  144.          /*
  145.           * Not a switch, so it must be a file name.
  146.           */
  147.          process( *argv );
  148.    }
  149. }
  150.  
  151. process( fn )
  152. char *fn;
  153. {
  154.    int type, c, i;
  155.    char name[ MAXLINELEN ];
  156.  
  157.    if ( !newfile( fn ) )
  158.       return;
  159.  
  160.    newpage();
  161.  
  162.    error( "" );
  163.    while ( getoken() )
  164.    {
  165.       if ( Token==INCLUDE )
  166.       {
  167.          /*
  168.           * Found a #include preprocessor directive.
  169.           * Search for file name immediately following
  170.           * a " or <
  171.           */
  172.          while ( (c = needchr()) != -1 && c!='"' && c!='<' )
  173.             ;
  174.          i = 0;
  175.          while ( (c = needchr()) != -1 && c!='"' && c!='>' )
  176.             if ( i<FILENMSZ )
  177.                name[ i++ ] = c;
  178.          name[ i ] = 0;
  179.          if ( Doincludes )
  180.          {
  181.             pushfile();
  182.             process( name );
  183.             popfile();
  184.             error( "" );
  185.          }
  186.       }
  187.       else if ( Token==DEFINE )
  188.       {
  189.          /*
  190.           * Print all #define preprocessor directives.
  191.           */
  192.          if ( Dodefines )
  193.             putstr( Tokenstart );
  194.          do
  195.          {
  196.             getoken();
  197.             if ( Dodefines )
  198.                putstr( Tokenbuf );
  199.          }
  200.          while ( Token!=NEWLINE );
  201.          if ( Debug && Dodefines )
  202.             printf( "<- #define ***\n" );
  203.       }
  204.       else if ( Token=='#' )
  205.       {
  206.          /*
  207.           * Skip all other preprocessor directives
  208.           */
  209.          while ( getoken() != NEWLINE );
  210.       }
  211.       else if ( Token==SYMBOL )
  212.       {
  213.          if ( Braces )
  214.          {
  215.             /*
  216.              * It's a symbol reference inside a function.
  217.              */
  218.             strcpy( name, Tokenstart );
  219.             reference( name );
  220.          }
  221.          else
  222.          {
  223.             /*
  224.              * It's a function (possibly) or some kinda
  225.              * typedef/define declaration, like:
  226.              *
  227.              *    FILE *fptr;
  228.              *
  229.              * We don't really know until we see the
  230.              * telltale ';' that tells us it's a decl.,
  231.              * or the '(' if it's a function, like:
  232.              *
  233.              *    FILE *fopen(f,m) char *f, *m; { ...
  234.              */
  235.             declaration( name );
  236.          }
  237.       }
  238.       else if ( Token <= DECLARATIONS )
  239.          declaration( name );
  240.    }
  241.    dumprefs();
  242.    flush();
  243.    endfile();
  244. }
  245.  
  246. declaration( name )
  247. char name[];
  248. {
  249.    /*
  250.     * It's definately a declaration of some kind, although it could be
  251.     * either a data declaration or a function definition or declaration,
  252.     * i.e., anything that resembles the following examples:
  253.     *
  254.     *    char *cp;
  255.     *    char *gets();
  256.     *    char *gets(buf,len,fp) ... {...
  257.     */
  258.    char brace, prevtoken;
  259.  
  260.    putstr( Tokenstart );
  261.    brace = Braces;
  262.    do
  263.    {
  264.       if ( Token==SYMBOL )
  265.       {
  266.          /*
  267.           * Previous token is a SYMBOL - save
  268.           * it just in case this is a function
  269.           * definition.
  270.           */
  271.          strcpy( name, Tokenstart );
  272.          prevtoken = SYMBOL;
  273.       }
  274.       else
  275.          prevtoken = 0;
  276.       /*
  277.        * Now get next input token
  278.        */
  279.       getoken();
  280.  
  281.       if ( Token=='(' && prevtoken==SYMBOL )
  282.       {
  283.          /*
  284.           * Function definitions and declarations are
  285.           * recognized by the telltale '('immediately
  286.           * following a SYMBOL token.
  287.           * It's a function definition if the first
  288.           * token following the "( ... )" is NOT a
  289.           * comma or semicolon, otherwise it's a
  290.           * declaration.
  291.           */
  292.          if ( Parens )
  293.             putstr( Tokenbuf );
  294.          while ( Parens )
  295.          {
  296.             getoken();
  297.             putstr( Tokenbuf );
  298.          }
  299.          getoken();
  300.          if ( Token!=',' && Token!=';' )
  301.          {
  302.             /*
  303.              * It's a function definition!
  304.              */
  305.             if ( Debug )
  306.                 printf("*** function ***");
  307.             putstr( "\n----------" );
  308.             /*
  309.              * Dump previous function's symbol references
  310.              * and copy current function's name into
  311.              * global "current function name buffer".
  312.              */
  313.             dumprefs();
  314.             strcpy( Curfunc, name );
  315.             goto done;
  316.          }
  317.          /*
  318.           * Otherwise, it's a function declaration of
  319.           * the form:
  320.           *
  321.           *    char *gets(), putc();
  322.           */
  323.       }
  324.       putstr( Tokenbuf );
  325.    }
  326.    while ( Token && (Token!=';' || Braces!=brace) );
  327.    /*
  328.     * If this is a global declaration, first dump current function's
  329.     * symbol references (if any).
  330.     */
  331.    if ( !Braces && Nextref )
  332.       dumprefs();
  333.  
  334.    if ( Debug )
  335.       printf( "<-declaration ***" );
  336. done:
  337.    putchr( '\n' );
  338.    flush();
  339. }
  340.  
  341. reference( name )
  342. char name[];
  343. {
  344.    /*
  345.     * It's a reference to a variable inside a function.
  346.     */
  347.    int c;
  348.  
  349.    while ( (c = getchr())!=-1 && (c==' ' || c=='\t' || c=='\n') );
  350.    ungetchr( c );
  351.  
  352.    if ( c == '(' )
  353.    {
  354.       /*
  355.        * Aha! it's a function call.
  356.        */
  357.       strcat( name, "()" );
  358.    }
  359.    addref( name );
  360. }
  361.  
  362. addref( name )
  363. char name[];
  364. {
  365.    char *cp, *getmem();
  366.    int i;
  367.  
  368.    for ( i=0; i<Nextref; ++i )
  369.       if ( !strcmp( name, Refers[ i ] ) )
  370.          return;
  371.  
  372.    if ( Nextref>=MAXREFS )
  373.       panic( "function references too many symbols" );
  374.    cp = Refers[ Nextref++ ] = getmem( strlen( name ) + 1 );
  375.    strcpy( cp, name );
  376. }
  377.  
  378. compar( a, b )
  379. char **a, **b;
  380. {
  381.    /*
  382.     * <Compare function> for qsort().
  383.     */
  384.    return strcmp( *a, *b );
  385. }
  386.  
  387. dumprefs()
  388. {
  389.    /*
  390.     * Sort and print current function's symbol reference table.
  391.     * Reinitialize symbol reference table.
  392.     */
  393.    int i;
  394.    char buf[ 80 ];
  395.  
  396.    if ( Nextref )
  397.    {
  398.       sprintf( buf, "Variables used by %s:\n", Curfunc );
  399.       outstr( buf );
  400.       qsort( Refers, Nextref, sizeof( Refers[0] ), compar );
  401.       for ( i=0; i<Nextref; ++i )
  402.       {
  403.          sprintf( buf, "\t%s\n", Refers[ i ] );
  404.          outstr( buf );
  405.          free( Refers[ i ] );
  406.       }
  407.       outstr( "----------\n\n\n" );
  408.       Nextref = 0;
  409.    }
  410. }
  411.  
  412. getoken()
  413. {
  414.    /*
  415.     * Read C tokens from current input file into the
  416.     * token buffer.  Strip out comments and whitespace in the
  417.     * process.
  418.     */
  419.    char   *tknptr;   /* Tokenbuf pointer */
  420.    int   c;      /* current input character */
  421.  
  422.    tknptr = Tokenbuf;
  423.  
  424. top:
  425.    if ( (c = getchr()) == -1 )
  426.       return *Tokenbuf = Token = 0;
  427.  
  428.    *tknptr++ = c;
  429.    /*
  430.     * Skip over spaces and tabs
  431.     */
  432.    if ( c==' ' || c=='\t' )
  433.       goto top;
  434.  
  435.    /*
  436.     * By default, token is the first non-space character in the
  437.     * input stream.  NOTE: newlines are not considered whitespace.
  438.     */
  439.    Token = c;
  440.    Tokenstart = tknptr - 1;
  441.  
  442.    if ( c=='\n' )
  443.       Token = NEWLINE;
  444.    else if ( c=='/' )
  445.    {
  446.       if ( (c = getchr()) == '*' )
  447.       {
  448.          if ( Docomments )
  449.             *tknptr++ = '*';
  450.          else
  451.             --tknptr;
  452.          while ( (c = needchr()) != -1 )
  453.          {
  454.             if ( Docomments )
  455.             {
  456.                if ( tknptr>=Tokenbuf+TOKENBUFSZ )
  457.                   panic( "buffer overflow" );
  458.                *tknptr++ = c;
  459.             }
  460.             if ( c=='*' )
  461.             {
  462.                if ( (c = needchr()) == '/' )
  463.                {
  464.                   if ( Docomments )
  465.                      *tknptr++ = '/';
  466.                   break;
  467.                }
  468.                else
  469.                   ungetchr( c );
  470.             }
  471.          }
  472.          Token = ' ';
  473.       }
  474.       else
  475.          ungetchr( c );
  476.    }
  477.    else if ( c=='#' )
  478.    {
  479.       while ( (c = getchr())!=-1 && (c==' ' || c=='\t') );
  480.       do
  481.       {
  482.          if ( (*tknptr++ = c) == '\\' )
  483.             *tknptr++ = getchr();
  484.       }
  485.       while ( (c = getchr())!=-1 && c!='\n' && c!=' ' && c!='\t' );
  486.       ungetchr( c );
  487.       *tknptr = 0;
  488.  
  489.       if ( strcmp( "#define", Tokenstart ) == 0 )
  490.          Token = DEFINE;
  491.       else if ( strcmp( "#include", Tokenstart ) == 0 )
  492.          Token = INCLUDE;
  493.    }
  494.    else if ( c=='{' )
  495.       ++Braces;
  496.    else if ( c=='}' )
  497.       --Braces;
  498.    else if ( c=='(' )
  499.       ++Parens;
  500.    else if ( c==')' )
  501.       --Parens;
  502.    else if ( alpha( c ) )
  503.    {
  504.       /*
  505.        * It's a symbol
  506.        */
  507.       while ( (c=getchr()) != -1 && alphanum( c ) )
  508.          *tknptr++ = c;
  509.       ungetchr( c );
  510.       *tknptr = 0;
  511.       /*
  512.        * Check if a keyword or variable.
  513.        */
  514.       if ( iskeyword( Tokenstart ) )
  515.          Token = KEYWORDS;
  516.       else if ( Token = isdecl( Tokenstart ) )
  517.          ;
  518.       else
  519.          Token = SYMBOL;
  520.    }
  521.    else if ( c == '"' )
  522.    {
  523.       /*
  524.        * It's a string constant
  525.        */
  526.       tknptr = string( tknptr, '"' );
  527.    }
  528.    else if ( c == '\'' )
  529.    {
  530.          /*
  531.           * It's a character constant
  532.           */
  533.       tknptr = string( tknptr, '\'' );
  534.    }
  535.    else if ( num( c ) )
  536.    {
  537.       /*
  538.        * It's a numeric constant
  539.        */
  540.       while ( (c=getchr()) != -1 && hex(c) )
  541.          *tknptr++ = c;
  542.       ungetchr( c );
  543.    }
  544.    *tknptr = 0;
  545.  
  546.    if ( Debug>1 )
  547.    {
  548.       if ( Token>' ' )
  549.          printf( "Token=%c\n", Token );
  550.       else
  551.          printf( "Token=<%d>\n", Token );
  552.       if ( Debug>2 )
  553.          printf( "<%s>\n", Tokenbuf );
  554.    }
  555.  
  556.    return Token;
  557. }
  558.  
  559. string( str, delim )
  560. char *str, delim;
  561. {
  562.    /*
  563.     * Compile a string from current input file into the given string
  564.     * buffer.  Stop when input character is the delimiter in "delim".
  565.     * Returns a pointer to the first character after the string.
  566.     */
  567.    int c;
  568.    char buf[ 4 ];
  569.  
  570.    while ( (c = getchr()) != -1 )
  571.    {
  572.       if ( (*str++ = c)  == '\\' )
  573.          *str++ = getchr();
  574.       if ( c==delim )
  575.          break;
  576.    }
  577.    *str = 0;
  578.  
  579.    return str;
  580. }
  581.  
  582. isdecl( name )
  583. char name[];
  584. {
  585.    if ( strcmp( "unsigned", name ) == 0 )
  586.       return UNSIGNED;
  587.    if ( strcmp( "char", name ) == 0 )
  588.       return CHAR;
  589.    if ( strcmp( "int", name ) == 0 )
  590.       return INT;
  591.    if ( strcmp( "long", name ) == 0 )
  592.       return LONG;
  593.    if ( strcmp( "float", name ) == 0 )
  594.       return FLOAT;
  595.    if ( strcmp( "double", name ) == 0 )
  596.       return DOUBLE;
  597.    if ( strcmp( "struct", name ) == 0 )
  598.       return STRUCT;
  599.    if ( strcmp( "union", name ) == 0 )
  600.       return UNION;
  601.  
  602.    if ( strcmp( "static", name ) == 0 )
  603.       return STATIC;
  604.    if ( strcmp( "extern", name ) == 0 )
  605.       return EXTERN;
  606.    if ( strcmp( "typedef", name ) == 0 )
  607.       return TYPEDEF;
  608.    if ( strcmp( "register", name ) == 0 )
  609.       return REGISTER;
  610.    if ( strcmp( "auto", name ) == 0 )
  611.       return AUTO;
  612.    if ( strcmp( "void", name ) == 0 )
  613.       return VOID;
  614.    if ( strcmp( "enum", name ) == 0 )
  615.       return ENUM;
  616.    return 0;
  617. }
  618.  
  619. iskeyword( name )
  620. char name[];
  621. {
  622.    if ( strcmp( "if", name ) == 0 )
  623.       return IF;
  624.    if ( strcmp( "else", name ) == 0 )
  625.       return ELSE;
  626.    if ( strcmp( "for", name ) == 0 )
  627.       return FOR;
  628.    if ( strcmp( "do", name ) == 0 )
  629.       return DO;
  630.    if ( strcmp( "while", name ) == 0 )
  631.       return WHILE;
  632.    if ( strcmp( "break", name ) == 0 )
  633.       return BREAK;
  634.    if ( strcmp( "continue", name ) == 0 )
  635.       return CONTINUE;
  636.    if ( strcmp( "goto", name ) == 0 )
  637.       return GOTO;
  638.    if ( strcmp( "return", name ) == 0 )
  639.       return RETURN;
  640.    if ( strcmp( "switch", name ) == 0 )
  641.       return SWITCH;
  642.    if ( strcmp( "case", name ) == 0 )
  643.       return CASE;
  644.    if ( strcmp( "default", name ) == 0 )
  645.       return DEFAULT;
  646.    if ( strcmp( "sizeof", name ) == 0 )
  647.       return SIZEOF;
  648.    return 0;
  649. }
  650.  
  651. /*
  652.  * File I/O functions
  653.  */
  654. newfile( fn )
  655. char *fn;
  656. {
  657.    /*
  658.     * Open the given file as the new current input file.
  659.     */
  660.    char msg[ 80 ];
  661.  
  662. #ifdef BDS_C
  663.    if ( fopen( fn, Fileptr ) == ERROR )
  664. #else
  665.    if ( !(Fileptr = fopen( fn, "r" )) )
  666. #endif
  667.    {
  668.       sprintf( msg, "can't open file '%s'", fn );
  669.       error( msg );
  670.       return 0;
  671.    }
  672.    else
  673.    {
  674.       Filename = fn;
  675.       Inline = 1;
  676.       return 1;
  677.    }
  678. }
  679.  
  680. endfile()
  681. {
  682.    /*
  683.     * Close out the current input file.
  684.     */
  685.    fclose( Fileptr );
  686.    Filename =
  687.    Inline = 0;
  688. }
  689.  
  690. pushfile()
  691. {
  692.    /*
  693.     * Push the current file  information onto a stack in preparation
  694.     * for #include file processing.
  695.     */
  696.    struct fstack *fsp;
  697.  
  698.    if ( Debug>1 )
  699.       printf( "*** pushfile(%s)\n", Filename );
  700.    if ( Nextfile >= FILESTACKSZ )
  701.       panic( "#includes nested too deeply" );
  702.    fsp = &Filestack[ Nextfile++ ];
  703.    strcpy( fsp->fname, Filename );
  704. #ifdef BDS_C
  705.    movemem( Fileptr, fsp->fptr, BUFSIZ );
  706. #else
  707.    fsp->fptr = Fileptr;
  708. #endif
  709.    fsp->fline = Inline;
  710.    fsp->fbraces = Braces;
  711.    fsp->fparens = Parens;
  712.    Parens = Braces = 0;
  713. }
  714.  
  715. popfile()
  716. {
  717.    struct fstack *fsp;
  718.  
  719.    if ( Nextfile-- )
  720.    {
  721.       fsp = &Filestack[ Nextfile ];
  722.       Filename = fsp->fname;
  723.       if ( Debug>1 )
  724.          printf( "*** popfile(%s)\n", Filename );
  725. #ifdef BDS_C
  726.       movemem( fsp->fptr, Fileptr, BUFSIZ );
  727. #else
  728.       Fileptr = fsp->fptr;
  729. #endif
  730.       Inline = fsp->fline;
  731.       Braces = fsp->fbraces;
  732.       Parens = fsp->fparens;
  733.    }
  734.    else
  735.       panic( "program error: popfile()" );
  736. }
  737.  
  738. getchr()
  739. {
  740.    int c;
  741.    char esc;
  742.  
  743.    c = getc( Fileptr );
  744. #ifdef BDS_C
  745.    if ( c=='\r' )
  746.    {
  747.       if ( (c = getc( Fileptr )) != '\n' )
  748.          ungetchr( c, Fileptr );
  749.       else
  750.          ++Inline;
  751.    }
  752. #endif
  753.    if ( c=='\n' )
  754.       ++Inline;
  755.  
  756.    return c;
  757. }
  758.  
  759. needchr()
  760. {
  761.    int c;
  762.  
  763.    if ( (c = getchr()) == -1 )
  764.       error( "unexpected EOF" );
  765.    return c;
  766. }
  767.  
  768. ungetchr( c )
  769. {
  770.    if ( c=='\n' )
  771.       --Inline;
  772.  
  773.    ungetc( c, Fileptr );
  774. }   
  775.  
  776. flush()
  777. {
  778.    char *cp;
  779.  
  780.    cp = Outbuf;
  781.    while ( cp < Nextout )
  782.    {
  783.       if ( *cp == '\n' )
  784.          if ( ++Outline >= PAGELEN )
  785.             newpage();
  786.       putchar( *cp++ );
  787.    }
  788.    Nextout = Outbuf;
  789. }
  790.  
  791. putchr( c )
  792. char c;
  793. {
  794.    if ( Nextout >= Outend )
  795.       flush();
  796.    *Nextout++ = c;
  797. }
  798.  
  799. putstr( s )
  800. char *s;
  801. {
  802.    while ( *s )
  803.    {
  804.       if ( Nextout >= Outend )
  805.          flush();
  806.       *Nextout++ = *s++;
  807.    }
  808. }
  809.  
  810. outstr( s )
  811. char *s;
  812. {
  813.    while ( *s )
  814.    {
  815.       if ( *s == '\n' )
  816.          if ( ++Outline >= PAGELEN )
  817.             newpage();
  818.       putchar( *s++ );
  819.    }
  820. }
  821.  
  822. newpage()
  823. {
  824.    Outline = 3;
  825.    printf( "\fC Variable Declarations/References in '%s'", Filename );
  826.    printf( "                     Page %d\n\n\n", ++Page );
  827. }
  828.  
  829. error( s )
  830. char *s;
  831. {
  832.    char buf[ 80 ];
  833.  
  834.    if ( Filename )
  835.    {
  836.       sprintf( buf, "%s: ", Filename );
  837.       outstr( buf );
  838.    }
  839.    if ( Inline )
  840.    {
  841.       sprintf( buf, "line %d: ", Inline );
  842.       outstr( buf );
  843.    }
  844.    sprintf( buf, "%s\n", s );
  845.    outstr( buf );
  846. }
  847.  
  848. usage()
  849. {
  850.    error( "Usage: var [-i] [-c] [-d] <file> ..." );
  851.    exit( 1 );
  852. }
  853.  
  854. panic( s )
  855. {
  856.    error( s );
  857.    exit( 2 );
  858. }
  859.  
  860. alpha( c )
  861. {
  862.    return ('A'<= c && c<='Z') || ('a'<=c && c<='z') || c=='_';
  863. }
  864.  
  865. num( c )
  866. {
  867.    return '0'<=c && c<='9';
  868. }
  869.  
  870. alphanum( c )
  871. {
  872.    return alpha( c ) || num( c );
  873. }
  874.  
  875. hex( c )
  876. {
  877.    return instring( c, "0123456789abcdefxlABCDEFXL" );
  878. }
  879.  
  880. movemem( from, to, count )
  881. char *from, *to;
  882. unsigned count;
  883. {
  884.    while ( count-- )
  885.       *to++ = *from++;
  886. }
  887.  
  888. char *
  889. getmem( size )
  890. unsigned size;
  891. {
  892.    char *cp;
  893.  
  894.    if ( cp = malloc( size ) )
  895.       return cp;
  896.  
  897.    panic( "out of memory" );
  898. }
  899.  
  900. instring( c, s )
  901. char c, *s;
  902. {
  903.    while ( *s )
  904.       if ( c==*s++ )
  905.          return 1;
  906.    return 0;
  907. }
  908.